运行环境
- Xcode 10.1
- Swift 4.2
背景知识
Swift 是一种强类型语言。即默认类型是安全的静态类型。纯Swift类的函数调用已经不再是OC的运行时发送消息,而是类似于C++的vtable,在编译时就确定了调用哪个函数,所以没法通过runtime获取方法,属性。Swift中的动态性可以通过OC运行时来获得,动态性最常用的就是方法替换(Method Swizzling)。
Swift中的动态修饰符
@objc: 将`Swift 函数 暴露给 OC运行时,但是它仍然不能保证完全动态,编译器会尝试去对它做静态优化@dynamic: 动态功能修饰符,它能保证函数,属性可以获得动态性
注意:继承自NSObject的Swift类,其继承自父类的方法具有动态性,因为是NSObject中的方法,其他在Swift中自定义方法,属性需要加@objc与@dynamic 必须同时加上者两个修饰符获得动态性,否则要报错"'dynamic' instance method 'sayHello' must also be '@objc'" 。若方法的参数,属性类型为Swift特有的,无法映射到OC的类型上(例如,Character,Tuple),不能添加@dynamic
定义一个需要替换方法实现的类(不继承NSObject)
1 | class SayHello { |
两种方案
- 方案一:用
Swift中的unsafeBitCast实现
扩展一个函数 swizzleSayHello()
1 | extension SayHello { |
调用函数
1 | SayHello.swizzleSayHello() |
打印:
1 | Hello Jack,nice to meet you! |
- 方案二:用
method_exchangeImplementations实现
同样扩展一个函数 swizzleSayHello() 以及实现一个目标函数swizzledSayHello(_ name: String)
1 | extension SayHello { |
调用函数
1 | SayHello.swizzledSayHello() |
打印:
1 | Hello Jack,nice to meet you! |
最后
@convention 关键字可以参考 @convention 以及 @convention